R Markdown

This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see http://rmarkdown.rstudio.com.

When you click the Knit button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this:

tickers <- c("NVDA", "AMD", "AC")
getSymbols(tickers, from = "2016-01-01", to = Sys.Date(), src = "yahoo")
## [1] "NVDA" "AMD"  "AC"
prices <- do.call(merge, lapply(tickers, function(x) Ad(get(x))))
colnames(prices) <- tickers
returns <- na.omit(ROC(prices, type = "discrete"))

# Descargar datos del IPC
getSymbols("^MXX", from = "2016-01-01", to = Sys.Date(), src = "yahoo")
## [1] "MXX"
ipc_prices <- Ad(MXX)
ipc_returns <- na.omit(ROC(ipc_prices, type = "discrete"))

# Calcular estadísticas para cada acción
stats <- function(ticker) {
  data <- na.omit(ROC(Ad(get(ticker)), type = "discrete"))
  list(
    Min = min(data),
    Max = max(data),
    Mean = mean(data),
    Variance = var(data),
    SharpeRatio = SharpeRatio.annualized(data, Rf = 0.01/252),
    Beta = CAPM.beta(data, ipc_returns, Rf = 0.01/252)
  )
}

stats_list <- lapply(tickers, stats)
stats_df <- do.call(rbind, lapply(stats_list, function(x) unlist(x)))
rownames(stats_df) <- tickers
colnames(stats_df) <- c("Min", "Max", "Mean", "Variance", "SharpeRatio", "Beta")
kable(stats_df, format = "html", table.attr = "class='table table-striped'") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"))
Min Max Mean Variance SharpeRatio Beta
NVDA -0.1875586 0.2980669 0.0028716 0.0009818 1.618666 0.7352442
AMD -0.2422908 0.5229008 0.0025977 0.0014125 1.007883 0.8870997
AC -0.1726670 0.4881807 0.0004002 0.0006386 0.034003 0.5018103
cov_matrix <- cov(returns)
kable(cov_matrix, format = "html", table.attr = "class='table table-striped'") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"))
NVDA AMD AC
NVDA 0.0009818 0.0007153 0.0001679
AMD 0.0007153 0.0014125 0.0001781
AC 0.0001679 0.0001781 0.0006386
print(cov_matrix)
##              NVDA          AMD           AC
## NVDA 0.0009817843 0.0007153074 0.0001679087
## AMD  0.0007153074 0.0014124551 0.0001780747
## AC   0.0001679087 0.0001780747 0.0006385676
data <- timeSeries(returns, charvec = index(returns))
spec <- portfolioSpec()
setRiskFreeRate(spec) <- 0.01
setNFrontierPoints(spec) <- 50

efficientFrontier <- portfolioFrontier(data, spec)
minvar_portfolio <- minvariancePortfolio(data, spec)
tangencyPortfolio <- tangencyPortfolio(data, spec)

optimal_weights <- getWeights(tangencyPortfolio)
print(optimal_weights)
##         NVDA          AMD           AC 
## 9.999997e-01 2.702695e-07 0.000000e+00
# Agregar CETES (activo libre de riesgo) al portafolio
risk_free_weight <- 0.10
optimal_weights <- (1 - risk_free_weight) * optimal_weights
optimal_weights <- c(optimal_weights, "CETES" = risk_free_weight)
print(optimal_weights)
##         NVDA          AMD           AC        CETES 
## 8.999998e-01 2.432426e-07 0.000000e+00 1.000000e-01
frontier_points <- data.frame(
  Risk = getTargetRisk(efficientFrontier),
  Return = getTargetReturn(efficientFrontier)
)


tangency_points <- data.frame(
  Risk = sd(portfolioReturn(tangencyPortfolio)), 
  Return = mean(portfolioReturn(tangencyPortfolio))
)

p1 <- plot_ly(frontier_points, x = ~Risk.Sigma, y = ~Return.mean, type = 'scatter', mode = 'line', 
              name = 'Frontera Eficiente', line = list(color = 'blue')) %>%
  add_trace(data = tangency_points, x = ~Risk, y = ~Return, type = 'scatter', mode = 'markers', 
            name = 'Portafolio Tangencial', marker = list(color = 'red', size = 10)) %>%
  layout(title = "Frontera Eficiente vs Portafolio Tangencial",
         xaxis = list(title = "Riesgo (Desviación Estándar)"),
         yaxis = list(title = "Rendimiento Esperado"))

p1
## Warning: Ignoring 1 observations
## A line object has been specified, but lines is not in the mode
## Adding lines to the mode...
## A line object has been specified, but lines is not in the mode
## Adding lines to the mode...
minvar_points <- data.frame(
  Risk = sd(portfolioReturn(minvar_portfolio)), 
  Return = mean(portfolioReturn(minvar_portfolio))
)

p2 <- plot_ly(frontier_points, x = ~Risk.Sigma, y = ~Return.mean, type = 'scatter', mode = 'lines', 
              name = 'Frontera Eficiente', line = list(color = 'blue')) %>%
  add_trace(data = minvar_points, x = ~Risk, y = ~Return, type = 'scatter', mode = 'markers', 
            name = 'Portafolio de Mínima Varianza', marker = list(color = 'green', size = 10)) %>%
  layout(title = "Frontera Eficiente vs Portafolio de Mínima Varianza",
         xaxis = list(title = "Riesgo (Desviación Estándar)"),
         yaxis = list(title = "Rendimiento Esperado"))

p2
## Warning: Ignoring 1 observations
## A line object has been specified, but lines is not in the mode
## Adding lines to the mode...
stats_df_df <- as.data.frame(stats_df)

sharpe_points <- data.frame(
  Asset = rownames(stats_df),
  SharpeRatio = stats_df_df$SharpeRatio
)

p3 <- plot_ly(frontier_points, x = ~Risk.Sigma, y = ~Return.mean, type = 'scatter', mode = 'lines', 
              name = 'Frontera Eficiente', line = list(color = 'red'))

# Gráfico del Ratio Sharpe (bar plot)
p4 <- plot_ly(sharpe_points, x = ~Asset, y = ~SharpeRatio, type = 'bar', 
              name = 'Ratio Sharpe', marker = list(color = 'blue'))

# Combinar los dos gráficos en un layout
p5 <- subplot(p3, p4) %>%
  layout(title = "Frontera Eficiente vs Ratio Sharpe",
         xaxis = list(title = "Acciones"),
         yaxis = list(title = "Valor"))

p5
port_returns <- Return.portfolio(returns, weights = optimal_weights[-length(optimal_weights)])
## Warning in Return.portfolio.geometric(R = R, weights = weights, wealth.index =
## wealth.index, : The weights for one or more periods do not sum up to 1:
## assuming a return of 0 for the residual weights
port_returns <- Return.portfolio(returns, weights = optimal_weights[-length(optimal_weights)])
## Warning in Return.portfolio.geometric(R = R, weights = weights, wealth.index =
## wealth.index, : The weights for one or more periods do not sum up to 1:
## assuming a return of 0 for the residual weights
performance <- merge(port_returns, ipc_returns, join = "inner")
colnames(performance) <- c("Portafolio", "IPC")

charts.PerformanceSummary(performance, main = "Desempeño Histórico del Portafolio vs. IPC")